/* sha1.c
**
** Copyright (c) 2007, Meadhbh S. Hamrick
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither the  name of  Project Meadhbh  nor the names of  its contributors
**    may be used  to endorse  or promote  products derived from this  software
**    without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
** 
** $Id: sha1.c 46 2007-08-30 16:52:27Z msh.mobile $
*/

/** \file sha1.c
 ** This file implements the SHA1 cryptographic hash function.
 */

/* Macro Definitions */

#ifndef MC_ROTATE_LEFT
#define MC_ROTATE_LEFT(x,n,b) (((x)<<(n))|((x)>>(b-n)))
#endif

#define MC_MIC_SHA1_CH(x,y,z) ( ( ( x ) & ( y ) )^ ( (~(x) ) & ( z ) ) )
#define MC_MIC_SHA1_PA(x,y,z) ( ( x ) ^ ( y ) ^ ( z ) )
#define MC_MIC_SHA1_MA(x,y,z) ( ( ( x ) & ( y ) ) ^ ( ( x ) & ( z ) ) ^ ( ( y ) & ( z ) ) )

/* File Includes */
#include "mutil.h"
#include "mcrypto/sha1.h"

/* Static Prototypes */

static void mc_mic_sha1_transform( tMCSha1 *context );

/* Static Variables */

void mc_mic_sha1_clone( tMCSha1 *new_context, tMCSha1 *old_context ) {
  memcpy( new_context, old_context, sizeof( tMCSha1 ) );
}

/** \fn tMCErr mc_mic_sha1_clear( tMCSha1 *context )
**  \brief clear sensitive data from the context
*/
void mc_mic_sha1_clear( tMCSha1 *context ) {
  mc_mic_sha1_initialize( context );
}

/** \fn tMCErr mc_mic_sha1_initialize( tMCSha1 *context )
**  \brief initialize a SHA1 context to it's initial condition
*/
void mc_mic_sha1_initialize( tMCSha1 *context ) {
  context->count = 0;

  memset( context->data.asChar, 0, 320 );

  context->state[0] = 0x67452301;
  context->state[1] = 0xEFCDAB89;
  context->state[2] = 0x98BADCFE;
  context->state[3] = 0x10325476;
  context->state[4] = 0xC3D2E1F0;
}
 
/** \fn tMCErr mc_mic_sha1_update( tMCSha1 *context, uint8_t *data, uint32_t length )
**  \brief provide input to the hash function
*/

void mc_mic_sha1_update( tMCSha1 *context, uint8_t *data, uint32_t length ) {
  uint32_t input_index;
  uint32_t block_index;

  for( input_index = 0; input_index < length; input_index ++ ) {

    /* copy data into the buffer */
    block_index = context->count % 64;
    context->data.asChar[ block_index ] = data[ input_index ];

    /* update the counter */
    context->count++;

    /* if the block buffer is full, transform the data */
    if( 63 == block_index ) {
      mc_mic_sha1_transform( context );
    }
  }
}

/** \fn tMCErr mc_mic_sha1_digest( tMCSha1 *context, uint8_t *digest )
**  \brief get the digest of the data provided
*/
void mc_mic_sha1_digest( tMCSha1 *context, uint8_t *digest ) {
  uint32_t next_pad_index;
  uint32_t i;

  /* where does the first padding byte go? */
  next_pad_index = ( context->count % 64 );

  /* put the first padding byte */
  context->data.asChar[ next_pad_index++ ] = 0x80;

  /* are we past the 56th byte in the data buffer? */

  if( next_pad_index > 55 ) {
    mc_mic_sha1_transform( context );
    next_pad_index = 0;
  }

  for( ; next_pad_index < 56; next_pad_index++ ) {
    context->data.asChar[ next_pad_index ] = 0;
  }

  /* append count to block */

  /* todo: find a platform independent way of doing a hton on long longs */
  context->data.asInt[ 15 ] = htonl( (context->count * 8) & 0xFFFFFFFF );

  /* call transform */

  mc_mic_sha1_transform( context );

  /* we may have to change state endianness */

  for( i=0; i<5; i++ ) {
    context->state[i] = htonl( context->state[i] );
  }

  /* copy state to digest */
  memcpy( digest, (uint8_t *) context->state, 20 );

}

/** \fn void mc_mic_sha1_transform( tMCSha1 *context )
**  \brief "churn" the internal state of the SHA1 context based on input data
*/
static void mc_mic_sha1_transform( tMCSha1 *context ) {
  uint32_t local_state[5];
  uint32_t t;
  uint32_t i;

  /* depending on the endianness of the processor, we may have to change */
  /* the endianness of the data array                                    */

  for( i = 0; i < 16; i++ ) {
    context->data.asInt[i] = ( uint32_t ) htonl( context->data.asInt[i] );
  }


  /* Prepare the Message Schedule */
  /* note: the update and digest calls already place the first 16 words of
  ** the message in the data member.
  */
  for( i=16; i<80; i++ ) {
    context->data.asInt[ i ] =
      MC_ROTATE_LEFT(
	(
	  context->data.asInt[ i -  3 ] ^
	  context->data.asInt[ i -  8 ] ^
	  context->data.asInt[ i - 14 ] ^
	  context->data.asInt[ i - 16 ]
	  ),
	1, 32);
  }

  /* Initialize Working Variables */

  local_state[ 0 ] = context->state[ 0 ];
  local_state[ 1 ] = context->state[ 1 ];
  local_state[ 2 ] = context->state[ 2 ];
  local_state[ 3 ] = context->state[ 3 ];
  local_state[ 4 ] = context->state[ 4 ];

  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[0];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[1];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[2];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[3];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[4];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[5];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[6];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[7];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[8];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[9];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[10];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[11];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[12];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[13];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[14];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[15];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[16];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[17];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[18];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;

  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_CH(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x5A827999 + 
    context->data.asInt[19];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;

  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[20];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[21];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[22];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[23];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[24];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[25];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[26];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[27];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[28];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[29];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[30];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[31];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[32];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[33];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[34];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[35];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[36];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[37];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[38];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x6ED9EBA1 + 
    context->data.asInt[39];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[40];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[41];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[42];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[43];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[44];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[45];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[46];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[47];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[48];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[49];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[50];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[51];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[52];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[53];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[54];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[55];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[56];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[57];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[58];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_MA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0x8F1BBCDC + 
    context->data.asInt[59];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[60];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[61];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[62];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[63];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[64];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[65];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[66];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[67];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[68];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[69];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[70];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[71];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[72];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[73];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[74];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[75];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[76];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[77];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[78];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  t = MC_ROTATE_LEFT( local_state[0], 5, 32 ) +
    MC_MIC_SHA1_PA(local_state[1],local_state[2],local_state[3]) +
    local_state[4] +
    0xCA62C1D6 + 
    context->data.asInt[79];
  local_state[4] = local_state[3];
  local_state[3] = local_state[2];
  local_state[2] = MC_ROTATE_LEFT(local_state[1],30,32);
  local_state[1] = local_state[0];
  local_state[0] = t;
    
  /* add the local_state back into the context state */
  context->state[ 0 ] += local_state[ 0 ];
  context->state[ 1 ] += local_state[ 1 ];
  context->state[ 2 ] += local_state[ 2 ];
  context->state[ 3 ] += local_state[ 3 ];
  context->state[ 4 ] += local_state[ 4 ];

  memset( context->data.asChar, 0, 320);
}
